"""几何计算工具模块"""
import numpy as np
from typing import Tuple

class CoordinateConverter:
    """坐标转换工具"""
    
    @staticmethod
    def xywh2xyxy(boxes: np.ndarray) -> np.ndarray:
        """将xywh格式转换为xyxy格式"""
        out = np.zeros_like(boxes)
        out[:, 0] = boxes[:, 0] - boxes[:, 2] / 2  # x1
        out[:, 1] = boxes[:, 1] - boxes[:, 3] / 2  # y1
        out[:, 2] = boxes[:, 0] + boxes[:, 2] / 2  # x2
        out[:, 3] = boxes[:, 1] + boxes[:, 3] / 2  # y2
        return out
    
    @staticmethod
    def label_to_xyxy(label_norm: np.ndarray, 
                     img_shape: Tuple[int, int]) -> np.ndarray:
        """将标准化标签转换为绝对坐标"""
        if label_norm.shape[0] == 0:
            return np.zeros((0, 5))
        
        h0, w0 = img_shape[:2]
        boxes = label_norm[:, 1:].copy()
        boxes[:, [0, 2]] *= w0
        boxes[:, [1, 3]] *= h0
        
        xyxy = CoordinateConverter.xywh2xyxy(boxes)
        return np.concatenate([label_norm[:, [0]], xyxy], axis=1)

class GeometryUtils:
    """几何计算工具"""
    
    @staticmethod
    def calculate_iou(box1: np.ndarray, box2: np.ndarray) -> np.ndarray:
        """计算两组边界框的IoU"""
        area1 = (box1[:, 2] - box1[:, 0]) * (box1[:, 3] - box1[:, 1])
        area2 = (box2[:, 2] - box2[:, 0]) * (box2[:, 3] - box2[:, 1])
        
        lt = np.maximum(box1[:, None, :2], box2[:, :2])
        rb = np.minimum(box1[:, None, 2:], box2[:, 2:])
        
        wh = np.clip(rb - lt, a_min=0, a_max=None)
        inter = wh[:, :, 0] * wh[:, :, 1]
        
        union = area1[:, None] + area2 - inter
        iou = inter / (union + 1e-6)
        
        return iou
    
    @staticmethod
    def nms(boxes: np.ndarray, scores: np.ndarray, iou_thresh: float = 0.5) -> list:
        """非极大值抑制"""
        idx = scores.argsort()[::-1]
        keep = []
        
        while idx.size > 0:
            i = idx[0]
            keep.append(i)
            
            if idx.size == 1:
                break
            
            ious = GeometryUtils.calculate_iou(
                boxes[i:i+1], boxes[idx[1:]]
            )[0]
            idx = idx[1:][ious < iou_thresh]
        
        return keep